/**
 * JAVACC DEMO 1.0
 */
package com.apache.rpc.client;

import com.apache.api.vo.ResultEntity;
import com.apache.exception.ServiceException;
import com.apache.rpc.common.MyX509TrustManager;
import com.apache.tools.StrUtil;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * description:  https通信接口实现
 *
 * @author Hou Dayu 创建时间：2016-10-28
 */
public class HttpsProtocolService extends AbstractProtocolService {

    private Logger logger = LoggerFactory.getLogger(HttpsProtocolService.class);

    /**
     * TODO 简单描述该方法的实现功能（可选）.
     */
    public ResultEntity doService(String beanId, String methodKey, Map<String, Object> params) {
        String paramType = StrUtil.doNull(String.valueOf(params.get("ParamType")), "xml");//返报文类型
        String xmlParams = this.buildXml(beanId, methodKey, "https", params);
        ResultEntity resultEntity = null;
        if (null == register) {
            resultEntity = getResultEntity("没有发布待执行的接口信息");
            return resultEntity;
        }
        String httpUrl = register.getAddress();
        try {
            String result = postHttp(httpUrl, xmlParams, paramType, "POST");
            String rows = StrUtil.doNull(String.valueOf(params.get("pageSize")),
                    String.valueOf(params.get("rows")));
            resultEntity = this.getResultEntity(result, paramType, rows);
        } catch (ServiceException e) {
            resultEntity = getResultEntity(e.getMessage());
        }
        return resultEntity;
    }

    public String doServiceStr(String beanId, String methodKey, Map<String, Object> params) {
        String paramType = StrUtil.doNull(String.valueOf(params.get("ParamType")), "xml");//返报文类型
        String xmlParams = this.buildXml(beanId, methodKey, "https", params);
        ResultEntity resultEntity = null;
        if (null == register) {
            return "";
        }
        String httpUrl = register.getAddress();
        try {
            return postHttp(httpUrl, xmlParams, paramType, "POST");
        } catch (ServiceException e) {
            return "";
        }
    }

    /**
     * post http 请求，接受返回的结果xml文档
     *
     * @param method POST/GET
     * @return xml类型字符串
     */
    private String postHttp(String httpsurl, String params, String type, String method) {
        String line = "";
        HttpsClient client = null;
        try {
            client = new HttpsClient();
            HttpResponse response = null;
            if ("GET".equals(method.toUpperCase())) {
                StringBuilder sb = new StringBuilder("");
                sb.append("?params=" + params);
                sb.append("&ParamType=" + type);
                sb.append("&httpRand=" + System.currentTimeMillis());
                HttpGet get = new HttpGet(httpsurl + sb.toString());
                response = client.execute(get);
            } else {
                HttpPost post = null;
                if(this.isSendBody()){
                    post = new HttpPost(httpsurl+"?httpRand="+ System.currentTimeMillis()+"&ParamType="+ type);
                    //参数转码
                    StringEntity uefEntity = new StringEntity(params, "UTF-8");
                    post.setEntity(uefEntity);
                    post.addHeader("Content-Type", "application/xml");
                }else {
                    post = new HttpPost(httpsurl);
                    // 创建参数队列
                    List<NameValuePair> formparams = new ArrayList<NameValuePair>(3);
                    formparams.add(new BasicNameValuePair("params", params));
                    formparams.add(new BasicNameValuePair("ParamType", type));
                    formparams.add(new BasicNameValuePair("httpRand",String.valueOf(System.currentTimeMillis())));
                    //参数转码
                    UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
                    post.setEntity(uefEntity);
                }
                response = client.execute(post);
            }
            HttpEntity entity = response.getEntity();
            if (null != entity) {
                line = EntityUtils.toString(entity);
                entity.consumeContent();
            }
        } catch (Exception e) {
            logger.error("异常",e);
        } finally {
            if (null != client) { // 关闭连接，腾出内存空间
                client.getConnectionManager().shutdown();
            }
        }
        return line;
    }

    class HttpsClient extends DefaultHttpClient {

        public HttpsClient() throws Exception {
            super();
            SSLContext ctx = SSLContext.getInstance("TLSv1.2");
            TrustManager[] tm = { new MyX509TrustManager() };
            ctx.init(null, tm, null);
            SSLSocketFactory ssf = new SSLSocketFactory(ctx);
            this.getConnectionManager().getSchemeRegistry().register(new Scheme("https", ssf, 443));
        }
    }
}
